#include "Logic.h"
#include "../Pulse-Tec/Include/PhysicsSystem.h"

#ifdef PSX_DEBUG
	#pragma comment(lib,"Pulse-Tecd.lib")
#else
	#pragma comment(lib,"Pulse-Tec.lib")
#endif

namespace Pulse
{
	const CHAR * GetApplicationName( void )
	{
		return PSX_String("Editor");
	}

	Logic * CreateApplicationLogic( void )
	{
		return new AppLogic;
	}

	void ReleaseApplicationLogic( Logic *pLogic )
	{
		delete pLogic;
	}

	AppLogic::AppLogic( void )
	{
		//AddView( new AppView );

	}

	AppLogic::~AppLogic( void )
	{
	
	}

	EErrorCode::Type AppLogic::OnInitialize( void )
	{ 
		PhysicsDummyFunction();

		// Test plane
		{
			Plane plane( 5.0f, 6.0f, 7.0f, 10.0f );
			float distance;
			Vector3 point( 5.0f, 6.0f, 7.0f );
		
			distance = plane.DistanceToPoint( &point );
			plane.Normalize();
			distance = plane.DistanceToPoint( &point );

			int x = 0;
		}

		// HACK: Hard coding window setup and configuration for now
		Application *pApp = GetApplication();
		WindowingSystem *pWindowSys = pApp->GetWindowingSystem();
		Window *pMainWindow = PSX_NULL;
		WindowView *pMainWindowView = PSX_NULL;

		EErrorCode::Type retCode;

		// Test Windows, Windowing System
		retCode = pWindowSys->CreateWindow_( PSX_String("Main Window"), &pMainWindow );
		//retCode = m_pWindowSys->CreateWindow_( PSX_String("Window 1"), &pMainWindow );
		//retCode = m_pWindowSys->CreateWindow_( PSX_String("Window 2"), &pMainWindow );
		//retCode = m_pWindowSys->CreateWindow_( PSX_String("Window 3"), &pMainWindow );

		// Test WindowViews
		retCode = pWindowSys->CreateWindowView( PSX_String("Main View"), &pMainWindowView );

		// Test Window-View functionality
		pMainWindow->InsertWindowView( pMainWindowView );

		// Test scene

		Scene *pMainScene = pMainWindowView->GetScene();

		// NOTE: Create actors and its components


		// Set Human Model
		{
			ActorPtr pActorHuman = pMainScene->NewActor();
			ComponentModelFilter *pCompModel = (ComponentModelFilter*)pActorHuman->AddComponent( EComponent::MODEL_FILTER );
			pActorHuman->AddComponent( EComponent::REFLECTION ); // Just testing the component

			retCode = pCompModel->LoadModel( PSX_String("Humanoid.mdl") );
			if ( retCode != EErrorCode::OKAY )
			{
				PSX_PushError( "Failed to load model!" );
			}
			pActorHuman->SetPosition( 0.0f, -5.0f, 10.0f );
			pActorHuman->SetRotation( 0.0f, 1.15f * PSX_PI, 0.0f );
			pActorHuman->SetScale( 0.05f );
			//ComponentPhysics *pCompPhys = (ComponentPhysics *)pActorHuman->AddComponent( EComponent::PHYSICS );
		}

		// Set model 1
		{
			ActorPtr pActorModel1 = pMainScene->NewActor();
			ComponentModelFilter *pCompModel = (ComponentModelFilter*)pActorModel1->AddComponent( EComponent::MODEL_FILTER );
			
			retCode = pCompModel->LoadModel( PSX_String("SadFace.mdl") );
			if ( retCode != EErrorCode::OKAY )
			{
				PSX_PushError( "Failed to load model!" );
			}
			pActorModel1->SetPosition( 2.5f, 0.0f, 12.0f );
			pActorModel1->SetRotation( 0.0f, 1.20f * PSX_PI, 0.0f );
			pActorModel1->SetScale( 0.1f );
			//ComponentPhysics *pCompPhys = (ComponentPhysics *)pActorModel1->AddComponent( EComponent::PHYSICS );
		}

		// Set model 2
		{
			ActorPtr pActorModel2 = pMainScene->NewActor();

		}


		// Set light
		{
			ActorPtr pActorLight = pMainScene->NewActor();
			ComponentLight *pCompLight = (ComponentLight*)pActorLight->AddComponent( EComponent::LIGHT );

			pActorLight->SetPosition( -5.0f, 2.0f, 8.0f );
			pCompLight->SetColor( &Vector3( 0.5f, 0.5f, 1.0f ) );
			pCompLight->SetColor( &Vector3( 1.0f, 1.0f, 1.0f ) );
			pCompLight->SetRange( 15.0f );

			m_pActorLight = pActorLight;

		}

		// Set camera
		{
			m_pActorCam = pMainScene->GetCamera();
			ComponentNativeScript *pComponentScript = (ComponentNativeScript*)m_pActorCam->AddComponent( EComponent::NATIVE_SCRIPT );
			pComponentScript->AttachScript<CSCameraControlFreeRoam>();
			m_pActorCam = PSX_NULL;
		}


		return EErrorCode::OKAY;
	}

	void AppLogic::OnShutdown( void )
	{
		m_pActorCam = PSX_NULL;
		m_pActorLight = PSX_NULL;
	}

	void AppLogic::OnUpdate( DOUBLE time, FLOAT dt )
	{
		if ( auto pActorLight = m_pActorLight.Lock() )
		{
			Matrix4x4 *pTrans = pActorLight->GetTransformWorld();
		
			float sinVal = Math::Sinf( time );
		
			if ( sinVal < 0.0f )
			{
				sinVal = sinVal - sinVal * 0.25f;
			}

			pActorLight->SetPosition( -5.0f, 2.0f + -sinVal * -5.0f, 8.0f + sinVal * -5.0f );
		}
	}
}